/**
 * 计数器持久化 Actor 示例
 * 
 * 这个示例展示如何创建一个简单的持久化 Actor，
 * 它可以接收增加和减少命令，并持久化事件。
 */
import { 
  ActorSystem, 
  PID, 
  PersistentActor,
  RecoverContext,
  CommandContext,
  PersistenceFactory
} from '../../src';

// 定义消息类型
enum CounterMessage {
  Increment = 'Increment',
  Decrement = 'Decrement',
  GetValue = 'GetValue'
}

// 定义事件类型
enum CounterEvent {
  Incremented = 'Incremented',
  Decremented = 'Decremented'
}

/**
 * 持久化计数器 Actor
 */
class CounterActor extends PersistentActor {
  // 计数器当前值
  private value: number = 0;
  // 持久化 ID
  private readonly _persistenceId: string;

  /**
   * 构造函数
   * @param id 计数器 ID
   */
  constructor(id: string) {
    super();
    this._persistenceId = `counter-${id}`;
  }

  /**
   * 获取持久化 ID
   */
  get persistenceId(): string {
    return this._persistenceId;
  }

  /**
   * 处理恢复事件
   * @param context 恢复上下文
   */
  receiveRecover(context: RecoverContext): void {
    const event = context.event;

    if (typeof event === 'object') {
      switch (event.type) {
        case CounterEvent.Incremented:
          this.value += event.amount || 1;
          console.log(`[恢复] 计数器增加: ${event.amount || 1}, 当前值: ${this.value}`);
          break;
        
        case CounterEvent.Decremented:
          this.value -= event.amount || 1;
          console.log(`[恢复] 计数器减少: ${event.amount || 1}, 当前值: ${this.value}`);
          break;
      }
    }
  }

  /**
   * 处理命令
   * @param context 命令上下文
   */
  receiveCommand(context: CommandContext): void {
    const message = context.message();

    if (typeof message === 'object') {
      switch (message.type) {
        case CounterMessage.Increment:
          const incrementAmount = message.amount || 1;
          // 持久化增加事件
          this.persist({ 
            type: CounterEvent.Incremented, 
            amount: incrementAmount,
            timestamp: Date.now()
          }).then(() => {
            // 事件持久化后更新状态
            this.value += incrementAmount;
            console.log(`计数器增加: ${incrementAmount}, 当前值: ${this.value}`);
            
            // 如果有发送者，返回当前值
            if (context.sender()) {
              context.respond({ value: this.value });
            }
          });
          break;
        
        case CounterMessage.Decrement:
          const decrementAmount = message.amount || 1;
          // 持久化减少事件
          this.persist({ 
            type: CounterEvent.Decremented, 
            amount: decrementAmount,
            timestamp: Date.now()
          }).then(() => {
            // 事件持久化后更新状态
            this.value -= decrementAmount;
            console.log(`计数器减少: ${decrementAmount}, 当前值: ${this.value}`);
            
            // 如果有发送者，返回当前值
            if (context.sender()) {
              context.respond({ value: this.value });
            }
          });
          break;
        
        case CounterMessage.GetValue:
          // 直接返回当前值，不持久化
          console.log(`获取计数器值: ${this.value}`);
          context.respond({ value: this.value });
          break;
      }
    }
  }

  /**
   * 当恢复完成时调用
   */
  protected onRecoveryCompleted(context: any): void {
    console.log(`计数器 ${this.persistenceId} 恢复完成，当前值: ${this.value}`);
  }
}

/**
 * 运行示例
 */
async function runExample() {
  // 创建 Actor 系统
  const system = new ActorSystem();
  
  // 初始化持久化工厂并创建内存持久化提供者
  const persistenceFactory = PersistenceFactory.getInstance();
  persistenceFactory.createInMemoryProvider();
  
  // 创建持久化 Actor
  // 注意：此处简化了实现，实际代码中需要通过 Props 和持久化工厂创建
  const counterActor = new CounterActor('123');
  const counterPid: PID = new PID('local', 'counter-123');
  
  // 发送增加命令
  await system.root.requestFuture(counterPid, { type: CounterMessage.Increment, amount: 5 }, 1000);
  
  // 发送减少命令
  await system.root.requestFuture(counterPid, { type: CounterMessage.Decrement, amount: 2 }, 1000);
  
  // 查询当前值
  const resultFuture = system.root.requestFuture(counterPid, { type: CounterMessage.GetValue }, 1000);
  const result = await resultFuture.result();
  console.log(`计数器最终值: ${result.value}`);
  
  // 停止 Actor
  system.root.stop(counterPid);
  
  // 终止 Actor 系统
  await system.terminate();
}

// 运行示例
runExample().catch(console.error); 